/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jeff.springWebTestNG.concurrent;

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class emulates the non-standard thread interruption, where for example 
 * I/O resource involved with which calling only 'interrupt()' cannot release
 * the resource correctly, therefore we must override it.
 * @author winnie
 */
public class NonStandardCancellationEmulator {
    
    
    private class Task implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(200);
            } catch (InterruptedException ex) {
                Logger.getLogger(CancellableThread.class.getName()).log(Level.WARNING, null, ex);
            }
        }
    }
    /**
     * This method will launch a framework, which override 'interrupt()' of an 
     * extended thread, to make it include shutting down the socket
     */
    public void startThreadExtending() {
        Thread cancellable = new CancellableThread(new Socket(), new Task());
        
        cancellable.start();
        
        try {//main thread sleep 100
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(NonStandardCancellationEmulator.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        cancellable.interrupt();
        //test whether correctly interrupted
        if (((CancellableThread)cancellable).socket == null) {
            System.out.println("Socket correctly closed & reset");
        }
    }
    
    private class CancellableThread extends Thread {
        Socket socket;

        public CancellableThread(Socket socket, Runnable r) {
            super(r);
            this.socket = socket;
        }
        

        @Override
        public void interrupt() {
            try {
                socket.close();
                socket = null;
            } catch (IOException ex) {
                Logger.getLogger(NonStandardCancellationEmulator.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                super.interrupt();
            }
        }
        
    }
    
    
    
    /**
     * This method will launch a framework, which override 'newTask' of an 
     * extended Future, to make it include shutting down the socket
     */
    public void startFutureExtending() {
        int corePoolSize = 3;
        int maximumPoolSize = 5;
        long keepAliveTime = 10;
        ThreadPoolExecutor exec = new ThreadPoolExecutor(
                corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()) {

            @Override
            protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
                if (callable instanceof CancellableTask) {
                    return ((CancellableTask) callable).newTask();
                } else 
                    return super.newTaskFor(callable);
            }
                    
        };
        
        
    }
    
    private interface CancellableTask<T> extends Callable<T> {
        RunnableFuture<T> newTask();
        void cancel();
    }
    
    private abstract class AbstractCancellableTask<T> implements CancellableTask<T> {

        @Override
        public void cancel() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public RunnableFuture<T> newTask() {
            return new FutureTask<T>(this) {

                @Override
                public boolean cancel(boolean bln) {
                    return super.cancel(bln);
                }
                
            };
        }
        
        
    }
    
}
